home *** CD-ROM | disk | FTP | other *** search
/ Gekkan Dennou Club 147 / Gekkan Dennou Club - 2000.8 Vol. 147 (Japan).7z / Gekkan Dennou Club - 2000.8 Vol. 147 (Japan) (Track 1).bin / docs / ippon / ver / 013 / enemy.c next >
C/C++ Source or Header  |  2000-07-07  |  6KB  |  274 lines

  1. /* enemy.c */
  2.  
  3. #include <stdio.h>
  4. #include <xsp2lib.h>
  5.  
  6. #include "main.h"
  7. #include "player.h"
  8. #include "shot.h"
  9. #include "enemy.h"
  10. #include "eshot.h"
  11. #include "effect.h"
  12. #include "psearch.h"
  13.  
  14. #define ENEMY_MAX    32    /* 敵最大数 */
  15.  
  16. static ENEMY enemy[ENEMY_MAX];    /* ワーク */
  17. static ENEMY *enemy_top,    /* 使用中のワークのリスト */
  18.  *enemy_null_top,        /* 空のワークのリスト */
  19.  *enemy_end;            /* 使用中ワークのリストの末尾 */
  20.  
  21.  
  22. /* 関数プロトタイプ宣言 */
  23. void EnemyAllocA (ENEMY *);
  24. int EnemyMoveA (ENEMY *);
  25. void EnemyAllocB (ENEMY *);
  26. int EnemyMoveB (ENEMY *);
  27.  
  28.  
  29. /* 初期化関数へのポインタの配列 */
  30. typedef void (*enemy_alloc) (ENEMY *);
  31. enemy_alloc EnemyAllocFunc[] =
  32. {
  33.     EnemyAllocA,
  34.     EnemyAllocB,
  35. };
  36.  
  37. /* 移動関数へのポインタの配列 */
  38. typedef int (*enemy_move) (ENEMY *);
  39. enemy_move EnemyMoveFunc[] =
  40. {
  41.     EnemyMoveA,
  42.     EnemyMoveB,
  43. };
  44.  
  45.  
  46. /* タイプAの敵の初期化ルーチン */
  47. void EnemyAllocA (ENEMY * p)
  48. {
  49.     p->pt = obj_zako02 + 15;
  50.     p->info = 0x0700 | PRIORITY_ZAKO;    /* 数値を決めうちして入れるのはよくない */
  51.     p->hit_sx = 12;        /* 自機ショットに対する当たり判定 */
  52.     p->hit_sy = 12;
  53.     p->hp = 1;        /* 耐久力 */
  54.     p->damage = 0;
  55. }
  56.  
  57. /* タイプAの敵の移動ルーチン */
  58. /* 返り値:非0なら消去 */
  59. int EnemyMoveA (ENEMY * p)
  60. {
  61.     /* 敵をくるくる回すアニメーション */
  62.     p->pt--;
  63.     if (p->pt < obj_zako02)
  64.         p->pt = obj_zako02 + 15;
  65.  
  66.     /* X座標を自機に近づける */
  67.     if (p->lx > player->lx)
  68.         p->lx -= 32768;
  69.     else
  70.         p->lx += 32768;
  71.  
  72.     p->ly += 2 * 65536;
  73.  
  74.     /* 上位ワード(固定整数部)だけ取り出す */
  75.     p->x = p->lx >> 16;
  76.     p->y = p->ly >> 16;
  77.  
  78.     if (p->y > 256 + 32)
  79.         return (-1);    /* Y座標が 256+32 以上なら消去 */
  80.  
  81.     /* もし前回ダメージを受けたなら */
  82.     if (p->damage) {
  83.         p->hp -= p->damage;
  84.         p->damage = 0;
  85.         /* 耐久力が0以下なら消去 */
  86.         if (p->hp <= 0) {
  87.             EffectAlloc (EFFECT_EXPLZAKO, 0, p->x, p->y);    /* 爆発パターンを出現させる */
  88.             return (-1);
  89.         }
  90.     }
  91.     xobj_set_st (p);    /* 表示 */
  92.  
  93.     return (0);
  94. }
  95.  
  96.  
  97. /* タイプBの敵の初期化ルーチン */
  98. void EnemyAllocB (ENEMY * p)
  99. {
  100.     p->pt = obj_zako02;
  101.     p->info = 0x0800 | PRIORITY_ZAKO;    /* 数値を決めうちして入れるのはよくない */
  102.     p->hit_sx = 12;        /* 自機ショットに対する当たり判定 */
  103.     p->hit_sy = 12;
  104.     p->hp = 2;        /* 耐久力 */
  105.     p->damage = 0;
  106.     p->s_work = 0;        /* ショット用ワークを初期化 */
  107. }
  108.  
  109. /* タイプBの敵の移動ルーチン */
  110. /* 返り値:非0なら消去 */
  111. int EnemyMoveB (ENEMY * p)
  112. {
  113.     /* 敵をくるくる回すアニメーション */
  114.     p->pt++;
  115.     if (p->pt > obj_zako02 + 15)
  116.         p->pt = obj_zako02;
  117.  
  118.  
  119.     /* X座標を自機に近づける */
  120.     if (p->lx > player->lx)
  121.         p->lx -= 32768;
  122.     else
  123.         p->lx += 32768;
  124.  
  125.     p->ly += 2 * 65536;
  126.  
  127.     /* 上位ワード(固定整数部)だけ取り出す */
  128.     p->x = p->lx >> 16;
  129.     p->y = p->ly >> 16;
  130.  
  131.     /* 弾を撃つ処理(30フレームに1回発射) */
  132.     if (p->s_work++ > 30) {
  133.         char angle;
  134.         p->s_work = 0;
  135.         angle = psearch (p->x, p->y);    /* 敵から見た自機の方向を unsigned char で返す */
  136.         EshotAlloc (0, p->x, p->y, 10, angle);    /* 弾を撃つ */
  137.     }
  138.     if (p->y > 256 + 32)
  139.         return (-1);    /* Y座標が 256+32 以上なら消去 */
  140.  
  141.     /* もし前回ダメージを受けたなら */
  142.     if (p->damage) {
  143.         p->hp -= p->damage;
  144.         p->damage = 0;
  145.         /* 耐久力が0以下なら消去 */
  146.         if (p->hp <= 0) {
  147.             EffectAlloc (EFFECT_EXPLZAKO, 0, p->x, p->y);    /* 爆発パターンを出現させる */
  148.             return (-1);
  149.         }
  150.     }
  151.     xobj_set_st (p);    /* 表示 */
  152.     return (0);
  153. }
  154.  
  155.  
  156.  
  157. /* ゲーム開始時に呼ばれる */
  158. void EnemyInit (void)
  159. {
  160.     int i;
  161.  
  162.     /* リストをつなげる */
  163.     enemy_top = NULL;
  164.     enemy_end = NULL;
  165.     enemy_null_top = enemy;
  166.     for (i = 0; i < ENEMY_MAX; i++)
  167.         enemy[i].next = &enemy[i + 1];
  168.  
  169.     enemy[ENEMY_MAX - 1].next = NULL;
  170. }
  171.  
  172.  
  173.  
  174. /* 敵出現時に呼ばれる */
  175. void EnemyAlloc (short type, signed short x, signed short y)
  176. {
  177.     ENEMY *p;
  178.  
  179.     if (enemy_null_top == NULL)
  180.         return;        /* 空きのワークがない(キャラクターオーバー) */
  181.  
  182.     /* リストの末尾に新しいノードを追加(他とは違うので注意) */
  183.     p = enemy_null_top;
  184.     enemy_null_top = p->next;
  185.     if (enemy_top == NULL)
  186.         enemy_top = p;
  187.     else
  188.         enemy_end->next = p;
  189.     p->next = NULL;
  190.     enemy_end = p;
  191.  
  192.     p->type = type;
  193.     p->lx = x << 16;
  194.     p->ly = y << 16;
  195.  
  196.     /* 関数へのポインタを使って分岐 */
  197.     /* type が 0 なら EnemyAllocA() が、1 なら EnemyAllocB() が実行される */
  198.     EnemyAllocFunc[p->type] (p);
  199.  
  200.     return;
  201. }
  202.  
  203.  
  204.  
  205. /* 垂直同期ごとに呼ばれる */
  206. void EnemyMove (void)
  207. {
  208.     ENEMY *p, *q;
  209.     signed short pl_x = player->x, pl_y = player->y;
  210.  
  211.     p = enemy_top;        /* 現在注目しているワーク */
  212.     q = NULL;        /* 1つ前のワーク(ワーク削除時に必要) */
  213.     while (p != NULL) {
  214.         /* 敵キャラの移動ルーチン */
  215.  
  216.         /* 関数へのポインタを使って分岐 */
  217.         /* type が 0 なら EnemyMoveA() が、1 なら EnemyMoveB() が実行される */
  218.  
  219.         if (EnemyMoveFunc[p->type] (p)) {    /* 返り値が非0なら消去 */
  220.             if (q == NULL) {    /* リストの一番最初を削除 */
  221.                 enemy_top = p->next;
  222.                 p->next = enemy_null_top;
  223.                 enemy_null_top = p;
  224.                 q = NULL;
  225.                 p = enemy_top;
  226.             } else {
  227.                 if (p == enemy_end) {    /* リストの一番最後を削除 */
  228.                     q->next = NULL;
  229.                     enemy_end = q;
  230.                     p->next = enemy_null_top;
  231.                     enemy_null_top = p;
  232.                     p = q->next;
  233.                 } else {
  234.                     q->next = p->next;
  235.                     p->next = enemy_null_top;
  236.                     enemy_null_top = p;
  237.                     p = q->next;
  238.                 }
  239.             }
  240.         } else {
  241.             /* 敵キャラを消去しない場合 */
  242.             SHOT *p2 = shot_top;    /* 現在注目しているショットのワーク */
  243.             signed short t;
  244.  
  245.             /* プレイヤーとの当たり判定 */
  246.             if (((t = p->x + p->hit_sx) > pl_x)
  247.                 && ((t -= (short) (p->hit_sx << 1)) < pl_x)
  248.                 && ((t = p->y + p->hit_sy) > pl_y)
  249.                 && ((t -= (short) (p->hit_sy << 1)) < pl_y)) {
  250.                 /* 当たった */
  251.                 if (player->status == PLAYER_STATUS_ALIVE)
  252.                     player->status = PLAYER_STATUS_DEAD;
  253.             }
  254.             /* ショットとの当たり判定 */
  255.             while (p2 != NULL) {
  256.                 signed short p2_w;
  257.                 short hit_w;
  258.                 if (((t = p->x + (hit_w = p->hit_sx)) >= (p2_w = *((short *) (&p2->lx))))
  259.                     && ((t -= (short) (hit_w << 1)) <= p2_w)
  260.                     && ((t = p->y + (hit_w = p->hit_sy)) >= (p2_w = *((short *) (&p2->ly))))
  261.                     && ((t -= (short) (hit_w << 1)) <= p2_w)
  262.                     && (p2->damage == 0)) {
  263.                     /* ショットが当たった */
  264.                     p->damage++;    /* 敵キャラにダメージを与える */
  265.                     p2->damage = !0;    /* 自機ショットに当たった事を知らせる */
  266.                 }
  267.                 p2 = p2->next;
  268.             }
  269.             q = p;
  270.             p = p->next;
  271.         }
  272.     }
  273. }
  274.